package com.dbh.company.buildbook.image;

import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;

import javax.imageio.*;
import javax.imageio.stream.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.Iterator;

public class OptimizedPNGDownscaler {

    public static void main(String[] args) {
        String imageUrl = "https://img.ljcdn.com/newhouse-user-image/f55760165f24cb68f57178ed055fb12d.png";
        String outputPath = "D:\\data0\\output_scaled.png";

        try {
            long startTime = System.currentTimeMillis();
            int sizeThreshold = 10000;
            int scaleFactor = 10;
            
            // 1. 下载图片到内存缓冲区（避免磁盘IO）
            byte[] imageData = HttpUtil.downloadBytes(imageUrl);

            // 2. 智能处理（单次读取）
            byte[] resultBytes = processImage(imageData, scaleFactor);
            FileUtil.writeBytes(resultBytes, outputPath);

            System.out.printf("总耗时: %.2f秒%n", (System.currentTimeMillis() - startTime) / 1000.0);
            
        } catch (Exception e) {
            System.err.println("处理失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 核心处理方法（单次读取）
     */
    private static byte[] processImage(byte[] imageData, int scaleFactor) throws IOException {
        try (ImageInputStream stream = ImageIO.createImageInputStream(new ByteArrayInputStream(imageData))) {
            // 获取图片信息而不解码像素
            Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
            if (!readers.hasNext()) throw new IOException("不支持的图片格式");

            ImageReader reader = readers.next();
            reader.setInput(stream);

            // 获取图片尺寸
            int width = reader.getWidth(0);
            int height = reader.getHeight(0);
            System.out.printf("原始尺寸: %dx%d%n", width, height);

            // 执行缩放处理
            System.out.printf("图片尺寸超过阈值，执行缩放 (1/%d)...%n", scaleFactor);
            BufferedImage scaledImage = scaleImage(reader, width, height, scaleFactor);

            // 将缩放后的图像写入到ByteArrayOutputStream
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(scaledImage, "png", outputStream);

            // 返回一个InputStream
            return outputStream.toByteArray();
        }
    }

    /**
     * 获取图片的宽度和高度
     */
    private static int[] getImageDimensions(byte[] imageData) throws IOException {
        try (ImageInputStream stream = ImageIO.createImageInputStream(new ByteArrayInputStream(imageData))) {
            // 获取图片信息而不解码像素
            Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
            if (!readers.hasNext()) throw new IOException("不支持的图片格式");

            ImageReader reader = readers.next();
            reader.setInput(stream);
            int width = reader.getWidth(0);
            int height = reader.getHeight(0);
            return new int[]{width, height};
        }
    }


    /**
     * 缩放图片核心逻辑
     */
    private static BufferedImage scaleImage(ImageReader reader, int width, int height, int scaleFactor) throws IOException {
        int scaledWidth = width / scaleFactor;
        int scaledHeight = height / scaleFactor;
        BufferedImage output = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
        
        Graphics2D g = output.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        
        // 分块处理
        int tileSize = calculateTileSize(scaledWidth, scaledHeight);
        System.out.println("分块处理中，区块大小: " + tileSize + "x" + tileSize);
        
        try {
            for (int y = 0; y < height; y += tileSize * scaleFactor) {
                for (int x = 0; x < width; x += tileSize * scaleFactor) {
                    // 动态计算区块大小
                    int tileWidth = Math.min(tileSize * scaleFactor, width - x);
                    int tileHeight = Math.min(tileSize * scaleFactor, height - y);
                    
                    // 读取并缩放区块
                    BufferedImage tile = readTile(reader, x, y, tileWidth, tileHeight, scaleFactor);
                    
                    // 绘制到目标图像
                    g.drawImage(
                        tile, 
                        x / scaleFactor,
                        y / scaleFactor,
                        tile.getWidth(), 
                        tile.getHeight(), 
                        null
                    );
                    
                    // 进度显示
                    System.out.printf("处理进度: %.1f%%\r", 
                        (double)(x + y * width) / (width * height) * 100);
                }
            }
        } finally {
            g.dispose();
            reader.dispose();
        }
        return output;
    }

    /**
     * 读取单个区块并缩放
     */
    private static BufferedImage readTile(ImageReader reader, int x, int y, int width, int height, int scaleFactor) throws IOException {
        ImageReadParam param = reader.getDefaultReadParam();
        param.setSourceRegion(new Rectangle(x, y, width, height));
        
        BufferedImage tile = reader.read(0, param);
        BufferedImage scaledTile = new BufferedImage(
            width / scaleFactor,
            height / scaleFactor,
            BufferedImage.TYPE_INT_RGB
        );
        
        Graphics2D g = scaledTile.createGraphics();
        g.drawImage(tile, 0, 0, scaledTile.getWidth(), scaledTile.getHeight(), null);
        g.dispose();
        
        return scaledTile;
    }

    /**
     * 计算最优区块大小
     */
    private static int calculateTileSize(int width, int height) {
        int max = Math.max(width, height);
        return max <= 2000 ? 1000 : Math.min(2000, max / 2);
    }

}